package de.sp.games.snake12k;

import java.util.ArrayList;

import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.SlickException;

import de.sp.games.snake12k.boxes.Box;
import de.sp.games.snake12k.boxes.EmptyBox;
import de.sp.games.snake12k.boxes.PickUpBox;
import de.sp.games.snake12k.boxes.SnakeBox;
import de.sp.games.snake12k.boxes.WallBox;

public class Field {

	private int x = (int) GameplayState.fieldX + 1;
	private int y = (int) GameplayState.fieldY + 1;
	
	private ArrayList<Box> boxList;
	public ArrayList<PickUpBox> picUpList;
	private SnakeBox snake;

	public Field() throws SlickException {

		boxList = new ArrayList<Box>();
		picUpList = new ArrayList<PickUpBox>();
		createNewField();
	}

	private void createNewField() throws SlickException {

		// Absolute Pixel Positionen
		int gridXPosition = 0;
		int gridYPosition = 0;

		for (int gridY = 1; gridY < y; gridY++) {
			for (int gridX = 1; gridX < x; gridX++) {
				if (checkForWall(gridX, gridY)) {
					boxList.add(new WallBox(gridXPosition, gridYPosition, gridX, gridY));
				} else {
					boxList.add(new EmptyBox(gridXPosition, gridYPosition, gridX, gridY));
				}
				gridXPosition += 16;
			}
			// New line
			gridXPosition = 0;
			gridYPosition += 16;
		}
		createSnakeRandom();
		createPickUpRandom();
		System.out.println("New Field Size: " + (x - 1) + "^2");
	}
	
	public void resetFieldWithNewField() throws SlickException {
		x = (int) GameplayState.fieldX + 1;
		y = (int) GameplayState.fieldY + 1;
		boxList = null;
		boxList = new ArrayList<Box>();
		picUpList = null;
		picUpList = new ArrayList<PickUpBox>();
		createNewField();
	}
	
	public void resetField() throws SlickException {
		x = (int) GameplayState.fieldX + 1;
		y = (int) GameplayState.fieldY + 1;
		boxList = null;
		boxList = new ArrayList<Box>();
		picUpList = null;
		picUpList = new ArrayList<PickUpBox>();
	}

	private boolean checkForWall(final int gridX, final int gridY) {
		boolean wall = false;

		if (gridY == 1 || gridX == 1 || gridY == y - 1 || gridX == x - 1) {
			wall = true;
		}
		return wall;
	}

	//TODO: Check for wall
	private void createSnakeRandom() throws SlickException {
		int randomX = randomNumberInSaveRange();
		int randomY = randomNumberInSaveRange();

		for (int i = 0; i < boxList.size(); i++) {
			if (boxList.get(i).getIndexX() == randomX && boxList.get(i).getIndexY() == randomY) {
				snake = new SnakeBox(randomX * 16 - 16, randomY * 16 - 16, randomX, randomY, boxList);
				boxList.add(snake);
				System.out.println("Snake @ X:" + randomX + " Y:" + randomY);
				break;
			}
		}
	}

	public void createPickUpRandom() throws SlickException {
		boolean isSave = false;
		int randomX = 0;
		int randomY = 0;
		
		/* create save Random Number */
		while(!isSave) {
			randomX = randomNumberInRange();
			randomY = randomNumberInRange();
			if(!SUtil.checkCollision(SUtil.getBoxArrayIndex(randomX, randomY, boxList), boxList)) {
				isSave = true;
				break;
			}
			System.out.println("Unsave!");
		}
		for (int i = 0; i < boxList.size(); i++) {
			if (boxList.get(i).getIndexX() == randomX && boxList.get(i).getIndexY() == randomY) {

				picUpList.add(new PickUpBox(randomX * 16 - 16, randomY * 16 - 16, randomX, randomY, snake, this));
				System.out.println("PickUp @ X:" + randomX + " Y:" + randomY);
				break;
			}
		}
	}

	private int randomNumberInRange() {
		int min = 2;
		int max = x - 1;

		return (int) (Math.random() * (max - min) + min);
	}
	
	private int randomNumberInSaveRange() {
		int min = (1 + (x / 3));
		int max = (x - (x / 3));

		return (int) (Math.random() * (max - min) + min);
	}

	public void draw(Graphics g) {
		for (int i = 0; i < boxList.size(); i++) {
			boxList.get(i).draw(g);
		}
		for(int i = 0; i < picUpList.size(); i++) {
			picUpList.get(i).draw(g);
		}
	}

	public void update(GameContainer gc) throws SlickException {
		for(int i = 1; i < boxList.size(); i++) {
			boxList.get(i).update(gc, boxList);
		}
		for(int i = 0; i < picUpList.size(); i++) {
			picUpList.get(i).update();
		}
		
		if(SUtil.isResetWithNewField()) {
			resetFieldWithNewField();
		}
	}
}
